package com.wonders.demo.enjoy.action.strategy.example3.spring.service;

import com.wonders.demo.enjoy.action.strategy.example3.spring.constant.PayModeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @desc 创建上下文管理，用于提取策略
 */
@Slf4j
@Component
public class PayStrategyContext {


    /**
     * 使用:
     * Autowired当使用在Collection里时，会将所申明类的所有实现类都放在那个指定的Collection里
     * 如果Autowired和map使用的话呢，它将它bean的名称作为key,所有的bean作为value
     */

//    @Autowired
//    List<PayStrategy> payStrategyList;
//
//
//    @Autowired
//    Map<String, PayStrategy> payStrategyMap;

    private final Map<String, PayStrategy> strategyMap = new ConcurrentHashMap<String, PayStrategy>();

    /**
     * 构造函数，把spring容器中所有关于该接口的子类，全部放入到集合中
     */
    public PayStrategyContext(List<PayStrategy> payStrategyList) {
        log.info("PayStrategy策略实现数量:{}", payStrategyList.size());
        for (PayStrategy payStrategy : payStrategyList) {
            strategyMap.put(payStrategy.getMode(), payStrategy);
        }
    }

    /**
     * 获取对应策略
     *
     * @param payModeEnum 支付方式枚举
     * @return 策略
     */
    public PayStrategy getStrategyByRuleType(PayModeEnum payModeEnum) {
        return strategyMap.get(payModeEnum.getCode());
    }


    public void useStrategy(String mode, BigDecimal price) {
        PayStrategy strategy = this.strategyMap.get(mode);
        if (strategy == null) {
            throw new RuntimeException("支付方式有误，请检查");
        }
        strategy.pay(price);
    }

    /**
     * 这种方式适用于传一个参数 所有的模式都去处理情况
     *
     * @param price 价格
     */
    public void handleAllRules(BigDecimal price) {
        PayModeEnum[] all = PayModeEnum.values();
        for (PayModeEnum payModeEnum : all) {
            strategyMap.get(payModeEnum.getCode()).pay(price);
        }
    }
}
